package org.particlethink.aop;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.particlethink.mapper.LogMapper;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Date;

@Aspect
@Component
public class LogAop {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private LogMapper logMapper;

    @Autowired
    private BeanFactory beanFactory;


    @Pointcut("@annotation(org.particlethink.aop.Log)")
    public void annotations() {
    }

    @Before("annotations()")
    public void before(final JoinPoint joinPoint) throws JsonProcessingException, IllegalAccessException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Log annotation = signature.getMethod().getAnnotation(Log.class);
        if (annotation == null){
            return;
        }

        Integer id = null;

        for (Object arg : joinPoint.getArgs()) {
            Class<?> clazz = arg.getClass();
            Id idAnnotation = clazz.getAnnotation(Id.class);
            if (idAnnotation != null) {
                id = (Integer) arg;
                break;
            }
            for (Field field : clazz.getDeclaredFields()) {
                idAnnotation = field.getAnnotation(Id.class);
                if (idAnnotation != null) {
                    field.setAccessible(true);
                    id = (Integer) field.get(arg);
                    break;
                }
            }
            if (id != null) {
                break;
            }
        }

        if (id == null || id == 0) {
            return;
        }

        Integer userId = (Integer) SecurityContextHolder.getContext().getAuthentication().getDetails();

        InfoById bean = beanFactory.getBean(annotation.id());
        Object info = bean.getInfoById(id);

        String jsonStr = objectMapper.writeValueAsString(info);

        org.particlethink.model.Log log = new org.particlethink.model.Log();
        log.setType(annotation.value());
        log.setContent(jsonStr);
        log.setCreateBy(userId);
        log.setDescription(annotation.description());
        log.setOtherId(id);
        log.setType(annotation.value());
        log.setCreateDate(new Date());
        logMapper.insert(log);

        System.out.println(jsonStr);
    }

}
